"""
菜鸟教程 https://www.runoob.com/w3cnote/python-redis-intro.html

channels文档 https://channels.readthedocs.io/en/latest/tutorial/part_2.html
"""


# --------- import和get_asgi_application()的位置顺序不能变!
import os
from django.core.asgi import get_asgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'websocket_my.settings')
django_asgi_app = get_asgi_application()
# ------- 必须在最前面, 不然部署的时候报错!


import channels.layers

channel_layer = channels.layers.get_channel_layer()

from asgiref.sync import async_to_sync

async_to_sync(channel_layer.send)('test_channel', {'type': 'hello'})
async_to_sync(channel_layer.receive)('test_channel')


fsend = async_to_sync(channel_layer.send)
fsend('123', {"a": 123})

freceive = async_to_sync(channel_layer.receive)
freceive('123')


# ----- 直接操作redis

import redis   # 导入redis 模块

r = redis.Redis(host='localhost', port=6379, decode_responses=True)
r.set('name', 'runoob')  # 设置 name 对应的值
print(r['name'])
print(r.get('name'))  # 取出键 name 对应的值
print(type(r.get('name')))  # 查看类型

r1 = redis.Redis(host='localhost', port=6379, decode_responses=True)
r1.set('name', 'runoob1')  # 设置 name 对应的值
print(r1['name'])
print(r1.get('name'))  # 取出键 name 对应的值
print(type(r1.get('name')))  # 查看类型

print(r['name'], r1['name'])


# ----- 连接池
EXPIRATION_TIME = 60*60*24*3        # 最大3天

pool = redis.ConnectionPool(host='localhost', port=6379, decode_responses=True)
r = redis.Redis(host='localhost', port=6379, decode_responses=True)
r.set('name', 'runoob')  # 设置 name 对应的值
print(r.get('name'))  # 取出键 name 对应的值

r.set('food', 'mutton122', ex=EXPIRATION_TIME, nx=True)
r.set('food', 'mutton1221', ex=EXPIRATION_TIME, xx=True)    # key是"food" value是"mutton" 将键值对存入redis缓存
print(r.get('food'))  # mutton 取出键food对应的值


r.set('x1', 'x1', ex=EXPIRATION_TIME)
r.set('x2', 'x22', ex=EXPIRATION_TIME)
r.set('x3', 'x333', ex=EXPIRATION_TIME)
r.set('x4', 'x4444', ex=EXPIRATION_TIME)
r.set('x5', 'x55555', ex=EXPIRATION_TIME)

print(r.get('x1'))
print(r.get('x2'))
print(r.get('x3'))
print(r.get('x4'))
print(r.get('x5'))

# r.set('x1', 'mutton122', ex=EXPIRATION_TIME)
# r.setrange("x5", 1, "ccc")
print(r.get('x5'))
r.strlen("x5")

print(r.mget("x1", "x2", "x3", "x4", "x5"))

r.append("x1", "haha")    # 在name对应的值junxi后面追加字符串haha
print(r.mget("x1"))

r.hset("hash1", "k1", "v1")
r.hset("hash1", "k2", "v2")
print(r.hkeys("hash1")) # 取hash中所有的key
print(r.hget("hash1", "k1"))    # 单个取hash的key对应的值
print(r.hmget("hash1", "k1", "k2")) # 多个取hash的key对应的值
r.hsetnx("hash1", "k2", "v3") # 只能新建
print(r.hget("hash1", "k2"))

r.hmset("hash2", {"k2": "v2", "k3": "v3"})
r.hget("hash2", 'k2')


print(r.hget("hash2", "k2"))  # 单个取出"hash2"的key-k2对应的value
print(r.hmget("hash2", "k2", "k3"))  # 批量取出"hash2"的key-k2 k3对应的value --方式1
print(r.hmget("hash2", ["k2", "k3"]))  # 批量取出"hash2"的key-k2 k3对应的value --方式2

print(r.hgetall("hash1"))
print(r.hlen("hash1"))

print(r.hexists("hash1", "k4"))  # False 不存在
print(r.hexists("hash1", "k1"))  # True 存在

print(r.hkeys("hash1"))
print(r.hvals("hash1"))

print(r.hgetall("hash1"))
r.hset("hash1", "k2", "v1222")   # 修改已有的key k2
r.hset("hash1", "k11", "v1")   # 新增键值对 k11
r.hdel("hash1", "k2")    # 删除一个键值对
print(r.hgetall("hash1"))
#
# r.hset("hash1", "k3", 123)
# r.hincrby("hash1", "k3", amount=-1)
# print(r.hgetall("hash1"))
#
# r.hset("hash1", "k5", "1.0")
# r.hincrbyfloat("hash1", "k5", amount=-1.0)    # 已经存在，递减-1.0
#
#
# r.lpush("list1", 11, 22, 33)
# print(r.lrange('list1', 0, -1))
#
# r.lindex('list1', 1)
# print(r.lrange('list1', 0, 0))
#
# r.rpush("list2", 44, 55, 66)    # 在列表的右边，依次添加44,55,66
# print(r.llen("list2"))  # 列表长度
# print(r.lrange("list2", 0, -1)) # 切片取出值，范围是索引号0到-1(最后一个元素)
#
# r.lpushx("list10", 10)   # 这里list10不存在
# print(r.llen("list10"))  # 0
# print(r.lrange("list10", 0, -1))  # []
# r.lpushx("list2", 77)   # 这里"list2"之前已经存在，往列表最左边添加一个元素，一次只能添加一个
# print(r.llen("list2"))  # 列表长度
# print(r.lrange("list2", 0, -1)) # 切片取出值，范围是索引号0到-1(最后一个元素
#
# r.lpop('list2')
# r.lindex('list2', 0)


user_id = '3124'
r.set('user_id', 1)
r.get('user_id')

r.hset('user_list', 'user_id', user_id)
r.hset('user_list', 'user_id', user_id)
r.hget('user_list')

r.set('order_id', 0)
r.get('order_id')

order_id = r.incr('order_id')
r.hmset("user_list", {"user_id": user_id, "order_id": order_id})
r.hgetall('user_list')

r.delete('user_list')
r.get('user_list')

r.hgetall('user_list')

r.lpush('user_list', 1)
r.rpush('user_list', 3)

print(r.lrange("user_list", 0, -1))


r.lrem("user_list", 1, '3')    # 将列表中所有的"3"删除
print(r.lrange("user_list", 0, -1))


r.rpop('user_list')
r.lrange('user_list', 0, -1)

print(r.lrange("user_list", 0, -1))


room_name = 'chat_1'
msg0 = 'haha000'
msg1 = 'haha111'

r.rpush("")


dic={
    "a1":"aa",
    "b1":"bb",
    "c1": {
        "cc1": 1,
        "cc2": 2,
    }
}
import json
r.set('x1', json.dumps(dic))
# r.set('x1', str(dic))
dc = r.get('x1')
dc
json.loads(dc)
eval(dc)

r.hmset("dic_name",dic)
print(r.hget("dic_name","b1"))#输出:bb


'''
redis存取字典
'''
redis = r
student = [{'name':'张三','content':'不会时间管理'},{'name':'罗志祥','content':'运动达人'}]
redis.set('student',str(student))#key-value存
print(redis.get('student'))
'''打印结果
[{'name':'张三','content':'不会时间管理'},{'name':'罗志祥','content':'运动达人'}]
'''


# 取出字典里的每个学生信息  eval将括号转换成字典
for key in eval(redis.get('student')):
    print('学生信息',key)


# 只想取name
print('学生姓名',key['name'])


# --- 集合

name = 'user_list'
r.delete(name)

value = 1
r.get(name)
r.sadd("set1", 33, 44, 55, 66)  # 往集合中添加元素
print(r.scard("set1"))  # 集合的长度是4
print(r.smembers("set1"))   # 获取集合中所有的成员
r.sismember(name, value)

k = 'set1'

for v in range(1, 10):      r.sadd(k, v)
r.smembers(k)

r.sismember(k, 1)
r.srem(k, 1)


k = 'list'
v = 2
for v in range(10, 20):     r.rpush(k, v)
# r.lpush(k, v)
r.lrange(k, 0, -1)


r.lpush("list5", 11, 22)
r.expire("list5", time=3)
print(r.lrange("list5", 0, -1))

print(r.lrange("list5", 0, -1))

r.delete(k)

type(r)


EXPIRATION_TIME = 5


class room_id_to_user_list:
    # 根据房间id, 查询该房间的user_list
    def __init__(self):
        self.r = r

    @staticmethod
    def get_room_name(room_id):
        key_name = f'room_{room_id}'
        r.expire(key_name, EXPIRATION_TIME)  # 超时时间

        return key_name

    @staticmethod
    def add_user_to_user_list(room_id, user_id):
        room_name = room_id_to_user_list.get_room_name(room_id)

        user_list = r.lrange(room_name, 0, -1)
        if str(user_id) not in user_list:
            ret = r.lpush(name, user_id)

            r.expire(room_name, EXPIRATION_TIME)  # 超时时间
            return ret
        else:
            print(f"--- 尝试添加已有用户[{user_id}]! ---")
            return 0

    @staticmethod
    def remove_user_from_user_list(room_id, user_id):
        room_name = room_id_to_user_list.get_room_name(room_id)
        r.lrem(room_name, 0, user_id)

    @staticmethod
    def show_user_list(room_id):
        room_name = room_id_to_user_list.get_room_name(room_id)

        print(r.lrange(room_name, 0, -1))



class user_id_compare_channel:
    # 用户id 和 用户channel 对照操作类
    def __init__(self):
        self.r= r

    @staticmethod
    def get_key_name(room_id):
        key_name = f'room_{room_id}:id_compare_channel'

        return key_name

    @staticmethod
    def save_room_user_channel(room_id, user_id, user_channel):
        # 各个房间的{用户id: channel}对照关系
        key_name = user_id_compare_channel.get_key_name(room_id)
        ret = r.hset(key_name, user_id, user_channel)
        r.expire(key_name, EXPIRATION_TIME)       # 超时时间

        return ret

    @staticmethod
    def get_user_channel_by_user_id(room_id, user_id):
        # 各个房间的{用户id: channel}对照关系
        key_name = user_id_compare_channel.get_key_name(room_id)
        ret = r.hget(key_name, user_id)
        return ret

    @staticmethod
    def show_all(room_id):
        key_name = user_id_compare_channel.get_key_name(room_id)
        return r.hgetall(key_name)


room_id = 111
user_id = 223
user_channel = "channel_2"

user_id_compare_channel.get_key_name(room_id)
user_id_compare_channel.save_room_user_channel(room_id, user_id, user_channel)
user_id_compare_channel.get_user_channel_by_user_id(room_id, user_id)
user_id_compare_channel.show_all(room_id)

